package org.example.scoresystem_backen.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.example.scoresystem_backen.entity.Score;
import org.example.scoresystem_backen.dto.PageRequest;
import org.example.scoresystem_backen.dto.ScoreDetailDTO;
import org.example.scoresystem_backen.dto.StudentOptionDTO;
import org.example.scoresystem_backen.dto.CourseOptionDTO;

import java.math.BigDecimal;
import java.util.List;

/**
 * 成绩数据访问Mapper接口
 */
@Mapper
public interface ScoreMapper {
    
    /**
     * 根据ID查找成绩
     * @param id 成绩ID
     * @return 成绩信息
     */
    Score findById(@Param("id") Integer id);
    
    /**
     * 查找所有成绩
     * @return 成绩列表
     */
    List<Score> findAll();
    
    /**
     * 根据学生ID查找成绩列表
     * @param studentId 学生ID
     * @return 成绩列表
     */
    List<Score> findByStudentId(@Param("studentId") Integer studentId);
    
    /**
     * 根据课程ID查找成绩列表
     * @param courseId 课程ID
     * @return 成绩列表
     */
    List<Score> findByCourseId(@Param("courseId") Integer courseId);
    
    /**
     * 根据学生ID和课程ID查找成绩
     * @param studentId 学生ID
     * @param courseId 课程ID
     * @return 成绩信息
     */
    Score findByStudentIdAndCourseId(@Param("studentId") Integer studentId, @Param("courseId") Integer courseId);
    
    /**
     * 根据成绩范围查找成绩列表
     * @param minScore 最低分
     * @param maxScore 最高分
     * @return 成绩列表
     */
    List<Score> findByScoreBetween(@Param("minScore") BigDecimal minScore, @Param("maxScore") BigDecimal maxScore);
    
    /**
     * 根据学生ID统计成绩数量
     * @param studentId 学生ID
     * @return 成绩数量
     */
    Long countByStudentId(@Param("studentId") Integer studentId);
    
    /**
     * 根据课程ID统计成绩数量
     * @param courseId 课程ID
     * @return 成绩数量
     */
    Long countByCourseId(@Param("courseId") Integer courseId);
    
    /**
     * 检查学生课程成绩是否存在
     * @param studentId 学生ID
     * @param courseId 课程ID
     * @return 是否存在
     */
    boolean existsByStudentIdAndCourseId(@Param("studentId") Integer studentId, @Param("courseId") Integer courseId);
    
    /**
     * 计算学生平均分
     * @param studentId 学生ID
     * @return 平均分
     */
    BigDecimal getAverageScoreByStudentId(@Param("studentId") Integer studentId);
    
    /**
     * 计算课程平均分
     * @param courseId 课程ID
     * @return 平均分
     */
    BigDecimal getAverageScoreByCourseId(@Param("courseId") Integer courseId);
    
    /**
     * 插入成绩
     * @param score 成绩信息
     * @return 影响行数
     */
    int insert(Score score);
    
    /**
     * 更新成绩信息
     * @param score 成绩信息
     * @return 影响行数
     */
    int update(Score score);
    
    /**
     * 根据ID删除成绩
     * @param id 成绩ID
     * @return 影响行数
     */
    int deleteById(@Param("id") Integer id);
    
    /**
     * 根据学生ID删除成绩
     * @param studentId 学生ID
     * @return 影响行数
     */
    int deleteByStudentId(@Param("studentId") Integer studentId);
    
    /**
     * 根据课程ID删除成绩
     * @param courseId 课程ID
     * @return 影响行数
     */
    int deleteByCourseId(@Param("courseId") Integer courseId);
    
    /**
     * 根据班级ID查找成绩列表（通过学生表关联）
     * @param classId 班级ID
     * @return 成绩列表
     */
    List<Score> findByClassId(@Param("classId") Integer classId);

    /**
     * 根据班级ID和课程ID查找成绩列表
     * @param classId 班级ID
     * @param courseId 课程ID
     * @return 成绩列表
     */
    List<Score> findByClassIdAndCourseId(@Param("classId") Integer classId, @Param("courseId") Integer courseId);

    /**
     * 根据考试日期范围查找成绩
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 成绩列表
     */
    List<Score> findByExamDateBetween(@Param("startDate") java.time.LocalDate startDate, @Param("endDate") java.time.LocalDate endDate);

    /**
     * 计算班级平均分
     * @param classId 班级ID
     * @return 平均分
     */
    BigDecimal calculateAverageScoreByClassId(@Param("classId") Integer classId);

    /**
     * 统计成绩总数
     * @return 成绩总数
     */
    Long count();

    /**
     * 根据班级ID统计成绩数量（通过学生表关联）
     * @param classId 班级ID
     * @return 成绩数量
     */
    Long countByClassId(@Param("classId") Integer classId);

    /**
     * 根据班级ID删除成绩（通过学生表关联）
     * @param classId 班级ID
     * @return 影响行数
     */
    int deleteByClassId(@Param("classId") Integer classId);

    // ========== 分页查询相关方法 ==========

    /**
     * 分页查询成绩详情（包含学生、课程、班级信息）
     * @param pageRequest 分页请求参数
     * @return 成绩详情列表
     */
    List<ScoreDetailDTO> findScoreDetailsWithPagination(@Param("pageRequest") PageRequest pageRequest);

    /**
     * 统计分页查询的总记录数
     * @param pageRequest 分页请求参数
     * @return 总记录数
     */
    Long countScoreDetailsWithConditions(@Param("pageRequest") PageRequest pageRequest);

    /**
     * 根据学生ID分页查询成绩详情（学生权限）
     * @param studentId 学生ID
     * @param pageRequest 分页请求参数
     * @return 成绩详情列表
     */
    List<ScoreDetailDTO> findScoreDetailsByStudentIdWithPagination(@Param("studentId") Integer studentId, @Param("pageRequest") PageRequest pageRequest);

    /**
     * 统计学生的成绩总数（学生权限）
     * @param studentId 学生ID
     * @param pageRequest 分页请求参数
     * @return 总记录数
     */
    Long countScoreDetailsByStudentIdWithConditions(@Param("studentId") Integer studentId, @Param("pageRequest") PageRequest pageRequest);

    // ========== 选项查询相关方法 ==========

    /**
     * 查询学生选项列表（用于下拉选择）
     * @return 学生选项列表
     */
    List<StudentOptionDTO> findStudentOptions();

    /**
     * 查询课程选项列表（用于下拉选择）
     * @return 课程选项列表
     */
    List<CourseOptionDTO> findCourseOptions();
}
